// 版权归Go作者所有。版权所有。
// 此源代码的使用受BSD样式的约束
// 可以在许可证文件中找到的许可证。

// 此文件实现了iimport.go的支持功能。

package gcimporter

import (
	"fmt"
	"go/token"
	"go/types"
	"sync"
)

func errorf(format string, args ...interface{}) {
	panic(fmt.Sprintf(format, args...))
}

// deltaNewFile是表示新文件的幻线增量偏移量。
// 我们使用-64是因为它很少见；见第20080期和第41619条。
// -64是作为变量放入单个字节的最小整数。
const deltaNewFile = -64

// 合成一个代币
type fakeFileSet struct {
	fset  *token.FileSet
	files map[string]*token.File
}

func (s *fakeFileSet) pos(file string, line, column int) token.Pos {
	// TODO（mdempsky）：使用列。

	// 由于我们不知道所需的文件位置集，因此
	// 保留每个文件的最大行位置。
	const maxlines = 64 * 1024
	f := s.files[file]
	if f == nil {
		f = s.fset.AddFile(file, -1, maxlines)
		s.files[file] = f
		// 首次使用时分配假换行索引。
		// TODO（adonovan）：选择：使用更复杂的方案保存~512KB？
		fakeLinesOnce.Do(func() {
			fakeLines = make([]int, maxlines)
			for i := range fakeLines {
				fakeLines[i] = i
			}
		})
		f.SetLines(fakeLines)
	}

	if line > maxlines {
		line = 1
	}

	// 将文件视为仅包含换行符
	// 列=1：使用行号作为偏移量。
	return f.Pos(line - 1)
}

var (
	fakeLines     []int
	fakeLinesOnce sync.Once
)

func chanDir(d int) types.ChanDir {
	// 标记值必须与cmd/compile/internal/gc/go.go中的常量匹配
	switch d {
	case 1 /* Crecv */ :
		return types.RecvOnly
	case 2 /* Csend */ :
		return types.SendOnly
	case 3 /* Cboth */ :
		return types.SendRecv
	default:
		errorf("unexpected channel dir %d", d)
		return 0
	}
}

var predeclared = []types.Type{
	// 基本类型
	types.Typ[types.Bool],
	types.Typ[types.Int],
	types.Typ[types.Int8],
	types.Typ[types.Int16],
	types.Typ[types.Int32],
	types.Typ[types.Int64],
	types.Typ[types.Uint],
	types.Typ[types.Uint8],
	types.Typ[types.Uint16],
	types.Typ[types.Uint32],
	types.Typ[types.Uint64],
	types.Typ[types.Uintptr],
	types.Typ[types.Float32],
	types.Typ[types.Float64],
	types.Typ[types.Complex64],
	types.Typ[types.Complex128],
	types.Typ[types.String],

	// 基本类型别名
	types.Universe.Lookup("byte").Type(),
	types.Universe.Lookup("rune").Type(),

	// 错误
	types.Universe.Lookup("error").Type(),

	// 非类型类型类型
	types.Typ[types.UntypedBool],
	types.Typ[types.UntypedInt],
	types.Typ[types.UntypedRune],
	types.Typ[types.UntypedFloat],
	types.Typ[types.UntypedComplex],
	types.Typ[types.UntypedString],
	types.Typ[types.UntypedNil],

	// 包装不安全
	types.Typ[types.UnsafePointer],

	// 无效类型
	types.Typ[types.Invalid], // 仅出现在有错误的包中

	// gc内部使用；此软件包或.a文件中从未使用过
	anyType{},
}

type anyType struct{}

func (t anyType) Underlying() types.Type { return t }
func (t anyType) String() string         { return "any" }
